﻿using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;

namespace PageAdmin.Utils
{
    /// <summary>
    /// RedisHelper 基础操作
    /// </summary>
    public partial class RedisHelper
    {
        private int DbNum { get; set; }
        /// <summary>
        /// Redis连接
        /// </summary>
        private readonly ConnectionMultiplexer _conn;

        /// <summary>
        /// 设置自定义键
        /// </summary>
        public string CustomKey;

        #region 构造函数

        /// <summary>
        /// 数据库名，默认0，做集群时候只能用0
        /// </summary>
        /// <param name="dbNum"></param>
        public RedisHelper(string redisHosts) : this(0, redisHosts)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbNum">数据库序号，做集群时候只能用0</param>
        /// <param name="redisHosts">自定义redis服务器</param>
        public RedisHelper(int dbNum, string redisHosts)
        {
            DbNum = dbNum;
            if (string.IsNullOrEmpty(redisHosts))
            {
                throw new Exception("redisHosts IsNullOrEmpty");
            }
            _conn = RedisConnectionHelper.DefaultConnectionString == null ?
                RedisConnectionHelper.GetConnectionMultiplexer(redisHosts) :
                RedisConnectionHelper.Instance;
        }

        #endregion 构造函数


        #region 发布订阅

        /// <summary>
        /// Redis发布订阅  订阅
        /// </summary>
        /// <param name="subChannel">订阅名称</param>
        /// <param name="handler">订阅的委托方法</param>
        public void Subscribe(string subChannel, Action<RedisChannel, RedisValue> handler = null)
        {
            ISubscriber sub = _conn.GetSubscriber();
            sub.Subscribe(subChannel, (channel, message) =>
            {
                //接收订阅消息，处理逻辑
                if (handler == null)
                {
                    Console.WriteLine(subChannel + " 订阅收到消息：" + message);
                }
                else
                {
                    handler(channel, message);
                }
            });
        }


        /// <summary>
        /// Redis发布订阅  发布
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="channel"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public long Publish<T>(string channel, T msg)
        {
            ISubscriber sub = _conn.GetSubscriber();
            return sub.Publish(channel, ConvertJson(msg));
        }

        /// <summary>
        /// Redis发布订阅  取消订阅
        /// </summary>
        /// <param name="channel"></param>
        public void Unsubscribe(string channel)
        {
            ISubscriber sub = _conn.GetSubscriber();
            sub.Unsubscribe(channel);
        }

        /// <summary>
        /// Redis发布订阅  取消全部订阅
        /// </summary>
        public void UnsubscribeAll()
        {
            ISubscriber sub = _conn.GetSubscriber();
            sub.UnsubscribeAll();
        }

        #endregion 发布订阅

        #region 其他
        /// <summary>
        /// 获取事务
        /// </summary>
        /// <returns></returns>
        public ITransaction CreateTransaction()
        {
            return GetDatabase().CreateTransaction();
        }

        /// <summary>
        /// 获取批处理（管道模式）
        /// </summary>
        /// <returns></returns>
        public IBatch CreateBatch()
        {
            return GetDatabase().CreateBatch();
        }

        public IDatabase GetDatabase()
        {
            return _conn.GetDatabase(DbNum);
        }

        public IServer GetServer(string hostAndPort)
        {
            return _conn.GetServer(hostAndPort);
        }


        #endregion 其他

        #region 辅助方法

        /// <summary>
        /// 定义一个公共方法
        /// </summary>
        /// <typeparam name="T">返回值为泛型</typeparam>
        /// <param name="func">参数为Idatabase,带返回值的委托</param>
        /// <returns></returns>
        public T Execute<T>(Func<IDatabase,T> func)
        {
            var database = _conn.GetDatabase(DbNum);
            return func(database);
        }

        /// <summary>
        /// 序列化
        /// </summary>
        /// <typeparam name="T">类</typeparam>
        /// <param name="value">值</param>
        /// <returns></returns>
        private string ConvertJson<T>(T value) 
        {
            string result = value is string ? value.ToString():JsonHelper.ToString(value);
            return result;
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        private T ConvertObj<T>(RedisValue value)
        {
            return JsonHelper.DeserializeObject<T>(value);
        }

        /// <summary>
        /// 反序列化列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="values"></param>
        /// <returns></returns>
        private IEnumerable<T> ConvetList<T>(RedisValue[] values)
        {
            List<T> result = new List<T>();
            foreach (var item in values)
            {
                var model = ConvertObj<T>(item);
                result.Add(model);
            }
            return result;
        }

        /// <summary>
        /// 转换为RedisKey结构数组
        /// </summary>
        /// <param name="redisKeys"></param>
        /// <returns></returns>
        private RedisKey[] ConvertRedisKeys(IEnumerable<string> redisKeys)
        {
            return redisKeys.Select(redisKey => (RedisKey)redisKey).ToArray();
        }

        #endregion 辅助方法
    }
}